package com.ccom.core.common.model;

import com.ccom.core.common.api.IResultCode;
import com.ccom.core.common.constant.ResultMsgConstant;
import com.ccom.core.common.enums.ExceptionEnums;
import com.ccom.core.common.enums.ResultCodeEnum;
import com.ccom.core.common.exception.CcomBootException;
import com.ccom.core.common.exception.RemindException;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.Optional;

/**
 * @author zjj
 * @date 2021/10/29
 * @description 接口返回对象
 */
@Data
@ApiModel(value = "接口返回对象", description = "接口返回对象")
public class Result<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "成功标志")
    private boolean success = true;

    @ApiModelProperty(value = "返回处理消息")
    private String message = "操作成功！";

    @ApiModelProperty(value = "返回代码")
    private Integer code = 0;

    @ApiModelProperty(value = "返回数据对象")
    private T result;

    @ApiModelProperty(value = "时间戳")
    private Long timestamp = System.currentTimeMillis();

    public Result() {
    }

    private Result(IResultCode resultCode) {
        this(resultCode, null, resultCode.getMessage());
    }

    private Result(IResultCode resultCode, String msg) {
        this(resultCode, null, msg);
    }

    private Result(IResultCode resultCode, T data) {
        this(resultCode, data, resultCode.getMessage());
    }

    private Result(IResultCode resultCode, T data, String msg) {
        this(msg, resultCode.getCode(), data);
    }

    private Result(String message, Integer code, T result) {
        this.message = message;
        this.code = code;
        this.result = result;
        this.success = HttpServletResponse.SC_OK == code;
    }

    /**
     * 判断返回是否为成功
     *
     * @param result Result
     * @return 是否成功
     */
    public static boolean isSuccess(@Nullable Result<?> result) {
        return Optional.ofNullable(result)
                .map(x -> ObjectUtils.nullSafeEquals(HttpServletResponse.SC_OK, x.code))
                .orElse(Boolean.FALSE);
    }

    /**
     * 判断返回是否为不成功
     *
     * @param result Result
     * @return 是否成功
     */
    public static boolean isNotSuccess(@Nullable Result<?> result) {
        return !Result.isSuccess(result);
    }

    /******************操作成功*********************/
    public static <T> Result<T> success() {
        return new Result<>(ResultCodeEnum.SUCCESS);
    }
    public static <T> Result<T> success(String message) {
        return new Result<>(ResultCodeEnum.SUCCESS, message);
    }
    public static <T> Result<T> date(T data) {
        return new Result<>(ResultCodeEnum.SUCCESS, data);
    }
    public static <T> Result<T> date(T data, String message) {
        return new Result<>(ResultCodeEnum.SUCCESS, data, message);
    }
    public static <T> Result<T> success(IResultCode resultCode) {
        return new Result<>(resultCode);
    }
    public static <T> Result<T> success(IResultCode resultCode, String message) {
        return new Result<>(resultCode, message);
    }
    /******************操作成功*********************/


    /******************操作失败*********************/
    public static <T> Result<T> error() {
        return new Result<>(ResultCodeEnum.FAILURE);
    }
    public static <T> Result<T> error(String message) {
        return new Result<>(ResultCodeEnum.FAILURE, message);
    }
    public static <T> Result<T> error(int code, String message) {
        return new Result<>(message, code, null);
    }
    public static <T> Result<T> error(CcomBootException e) {
        return new Result<>(e.getDefaultMessage(), e.getCode(), null);
    }
    public static <T> Result<T> error(IResultCode resultCode) {
        return new Result<>(resultCode);
    }
    public static <T> Result<T> error(IResultCode resultCode, String message) {
        return new Result<>(resultCode, message);
    }
    /******************操作失败*********************/


    /******************操作提醒*********************/
    public static <T> Result<T> remind(RemindException e) {
        return new Result<T>(e.getDefaultMessage(), e.getCode(), null);
    }
    public static <T> Result<T> remind(ExceptionEnums e) {
        return new Result<T>(e.getMessage(), e.getCode(), null);
    }
    public static <T> Result<T> remind(String message) {
        return remind(message, 600);
    }
    public static <T> Result<T> remind(String message, int code) {
        return new Result<T>(message, code, null);
    }
    /******************操作提醒*********************/


    public static <T> Result<T> status(boolean flag) {
        return flag ? success(ResultMsgConstant.DEFAULT_SUCCESS_MESSAGE) : error(ResultMsgConstant.DEFAULT_FAILURE_MESSAGE);
    }
}